import tkinter as tk
from typing import List
from rikapycli.Commander import Commander

_style: dict = {
    'fg': '#eeeeee',
    'bg': '#444466',
    'font': ('DejaVu Sans Mono', 11, 'normal')
}
_pack_args = {
    'padx': 5,
    'pady': 5,
    'ipadx': 15,
    'ipadx': 15
}


class TkTerminal:
    def __init__(self, commander: Commander,
                 title: str = 'Tk Terminal',
                 geometry: str = '1000x700') -> None:
        self.app = tk.Tk()
        self.app['background'] = _style['bg']
        self.app.title(title)
        self.app.geometry(geometry)
        self.entry = tk.Entry(self.app, **_style)
        self.text = tk.Text(self.app, **_style)
        self.text['state'] = 'disabled'
        self.commander = commander
        self.entry.bind('<Key>', self.on_key_down)
        self.write('\n' * 30)

    def show(self) -> None:
        self.text.pack(fill='both', **_pack_args)
        self.entry.pack(fill='both', **_pack_args)
        self.entry.focus()
        self.app.mainloop()

    def write(self, content: str, new_line: bool = True):
        self.text['state'] = 'normal'
        if new_line:
            c: str = self.text.get('0.0', tk.END)
            if not c.endswith('\n'):
                content = '\n' + content
            if not content.endswith('\n'):
                content += '\n'

        self.text.insert('insert', content)
        self.text.yview_scroll(9999999, tk.PAGES)
        self.text['state'] = 'disabled'

    def clear_command(self):
        self.entry.delete(0, 999999999)

    def set_command(self, command: str):
        self.clear_command()
        self.entry.insert(tk.INSERT, command)

    def get_command(self) -> str:
        return self.entry.get()

    def on_key_down(self, args: tk.Event):
        # Enter:36   Up:111   Down:116
        if args.keycode == 36:
            c = self.get_command()
            if not c:
                return
            result = self.commander.commit(c)
            out: List[str] = [f"\n> {c}"]
            if result.code != 0:
                out.append(f'Code: {result.code}')
            if result.message:
                out.append(result.message)
            if result.result:
                out.append(f'Result: {result.result}')
            self.write('\n'.join(out))
            self.clear_command()

        elif args.keycode == 111:
            r = self.commander.switch_previous(self.get_command())
            self.set_command(r)
        elif args.keycode == 116:
            r = self.commander.switch_next(self.get_command())
            self.set_command(r)
